home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / NRS.C < prev    next >
C/C++ Source or Header  |  1996-12-28  |  6KB  |  235 lines

  1. /* This module implements the serial line framing method used by
  2.  * net/rom nodes.  This allows the net/rom software to talk to
  3.  * an actual net/rom over its serial interface, which is useful
  4.  * if we want to do packet switching for multi-line wormholes.
  5.  * Copyright 1989 Dan Frank, W9NK
  6.  */
  7. #include "global.h"
  8. #ifdef NETROM
  9. #ifdef NRS
  10. #include "commands.h"
  11. #include "mbuf.h"
  12. #include "iface.h"
  13. #include "pktdrvr.h"
  14. #include "nrs.h"
  15. #include "asy.h"
  16. #include "trace.h"
  17.  
  18. #if !defined(_lint)
  19. static char rcsid[] OPTIONAL = "$Id: nrs.c,v 1.12 1996/12/29 02:47:22 root Exp root $";
  20. #endif
  21.  
  22.  
  23. static struct mbuf *nrs_encode (struct mbuf * bp);
  24. static struct mbuf *nrs_decode (int dev, char c);
  25.  
  26. /* control structures, sort of overlayed on async control blocks */
  27. struct nrs *Nrs;
  28.  
  29.  
  30. /* Send a raw net/rom serial frame */
  31. int
  32. nrs_raw (struct iface *iface, struct mbuf *bp)
  33. {
  34. struct mbuf *bp1;
  35.  
  36.     dump (iface, IF_TRACE_OUT, CL_AX25, bp);
  37.     iface->rawsndcnt++;
  38.     iface->lastsent = secclock ();
  39.  
  40.     if ((bp1 = nrs_encode (bp)) == NULLBUF) {
  41.         free_p (bp);
  42.         return -1;
  43.     }
  44.     return Nrs[iface->xdev].send (iface->dev, bp1);
  45. }
  46.  
  47.  
  48. /* Encode a packet in net/rom serial format */
  49. static struct mbuf *
  50. nrs_encode (struct mbuf *bp)
  51. {
  52. struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  53. register char *cp;
  54. int c;
  55. unsigned char csum = 0;
  56. struct mbuf **bpp = &bp;
  57.  
  58.     /* Allocate output mbuf that's twice as long as the packet.
  59.      * This is a worst-case guess (consider a packet full of STX's!)
  60.      * Add five bytes for STX, ETX, checksum, and two nulls.
  61.      */
  62.     lbp = alloc_mbuf ((int16) (2 * len_p (bp) + 5));
  63.     if (lbp == NULLBUF) {
  64.         /* No space; drop */
  65.         free_p (bp);
  66.         return NULLBUF;
  67.     }
  68.     cp = (char *) lbp->data;
  69.  
  70.     *cp++ = STX;
  71.  
  72.     /* Copy input to output, escaping special characters */
  73.     while ((c = PULLCHAR (bpp)) != -1) {
  74.         switch (c) {
  75.             case STX:
  76.             case ETX:
  77.             case DLE:
  78.                 *cp++ = DLE;
  79.                 /* notice drop through to default */
  80.             default:
  81.                 *cp++ = (char) c;
  82.         }
  83.         csum += uchar(c);
  84.     }
  85.     *cp++ = ETX;
  86.     *cp++ = (char) csum;
  87.     *cp++ = NUL;
  88.     *cp++ = NUL;
  89.  
  90.     lbp->cnt = (int16) (cp - (char *) lbp->data);
  91.     return lbp;
  92. }
  93.  
  94.  
  95. /* Process incoming bytes in net/rom serial format
  96.  * When a buffer is complete, return it; otherwise NULLBUF
  97.  */
  98. static struct mbuf *
  99. nrs_decode (dev, c)
  100. int dev;            /* net/rom unit number */
  101. char c;                /* Incoming character */
  102. {
  103. struct mbuf *bp;
  104. register struct nrs *sp;
  105.  
  106.     sp = &Nrs[dev];
  107.     switch (sp->state) {
  108.         case NRS_INTER:
  109.             if (uchar (c) == STX) {    /* look for start of frame */
  110.                 sp->state = NRS_INPACK;    /* we're in a packet */
  111.                 sp->csum = 0;    /* reset checksum */
  112.             }
  113.             return NULLBUF;
  114.         case NRS_CSUM:
  115.             bp = sp->rbp;
  116.             sp->rbp = NULLBUF;
  117.             sp->rcnt = 0;
  118.             sp->state = NRS_INTER;    /* go back to inter-packet state */
  119.             if (sp->csum == uchar (c)) {
  120.                 sp->packets++;
  121.             } else {
  122.                 free_p (bp);    /* drop packet with bad checksum */
  123.                 bp = NULLBUF;
  124.                 sp->errors++;    /* increment error count */
  125.             }
  126.             return bp;
  127.         case NRS_ESCAPE:
  128.             sp->state = NRS_INPACK;    /* end of escape */
  129.             break;    /* this will drop through to char processing */
  130.         case NRS_INPACK:
  131.             switch (uchar (c)) {
  132.                     /* If we see an STX in a packet, assume that previous */
  133.                     /* packet was trashed, and start a new packet */
  134.                 case STX:
  135.                     free_p (sp->rbp);
  136.                     sp->rbp = NULLBUF;
  137.                     sp->rcnt = 0;
  138.                     sp->csum = 0;
  139.                     sp->errors++;
  140.                     return NULLBUF;
  141.                 case ETX:
  142.                     sp->state = NRS_CSUM;    /* look for checksum */
  143.                     return NULLBUF;
  144.                 case DLE:
  145.                     sp->state = NRS_ESCAPE;
  146.                     return NULLBUF;
  147.                 default:
  148.                     break;
  149.             }
  150.             break;
  151.         default:
  152.             break;
  153.     }
  154.     /* If we get to here, it's with a character that's part of the packet.
  155.      * Make sure there's space for it.
  156.      */
  157.     if (sp->rbp == NULLBUF) {
  158.         /* Allocate first mbuf for new packet */
  159.         if ((sp->rbp1 = sp->rbp = alloc_mbuf (NRS_ALLOC)) == NULLBUF) {
  160.             sp->state = NRS_INTER;
  161.             return NULLBUF;    /* No memory, drop */
  162.         }
  163.         sp->rcp = (char *) sp->rbp->data;
  164.     } else if (sp->rbp1->cnt == NRS_ALLOC) {
  165.         /* Current mbuf is full; link in another */
  166.         if ((sp->rbp1->next = alloc_mbuf (NRS_ALLOC)) == NULLBUF) {
  167.             /* No memory, drop whole thing */
  168.             free_p (sp->rbp);
  169.             sp->rbp = NULLBUF;
  170.             sp->rcnt = 0;
  171.             sp->state = NRS_INTER;
  172.             return NULLBUF;
  173.         }
  174.         sp->rbp1 = sp->rbp1->next;
  175.         sp->rcp = (char *) sp->rbp1->data;
  176.     }
  177.     /* Store the character, increment fragment and total
  178.      * byte counts
  179.      */
  180.     *sp->rcp++ = c;
  181.     sp->rbp1->cnt++;
  182.     sp->rcnt++;
  183.     sp->csum += uchar (c);    /* add to checksum */
  184.     return NULLBUF;
  185. }
  186.  
  187.  
  188. /* Process net/rom serial line I/O */
  189. void
  190. nrs_recv (int dev, void *v1 OPTIONAL, void *v2 OPTIONAL)
  191. {
  192. char c;
  193. struct mbuf *bp, *nbp;
  194. struct phdr phdr;
  195.  
  196.     /* Process any pending input */
  197.     for (;;) {
  198.         c = (char) Nrs[dev].get (Nrs[dev].iface->dev);
  199.         if ((bp = nrs_decode (dev, c)) == NULLBUF)
  200.             continue;
  201.         if ((nbp = pushdown (bp, sizeof (phdr))) == NULLBUF) {
  202.             free_p (bp);
  203.             continue;
  204.         }
  205.         phdr.iface = Nrs[dev].iface;
  206.         phdr.type = CL_AX25;
  207.         memcpy (&nbp->data[0], (char *) &phdr, sizeof (phdr));
  208.         enqueue (&Hopper, nbp);
  209.     }
  210.  
  211. }
  212.  
  213.  
  214. /* donrstat:  display status of active net/rom serial interfaces */
  215. int
  216. donrstat (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  217. {
  218. register struct nrs *np;
  219. register int i;
  220.  
  221.     tputs ("Interface   RcvB  NumReceived  CSumErrors\n");
  222.  
  223.     for (i = 0, np = Nrs; i < ASY_MAX; i++, np++)
  224.         if (np->iface != NULLIF)
  225.             if (tprintf (" %8s   %4d   %10lu  %10lu\n",
  226.                      np->iface->name, np->rcnt,
  227.                      np->packets, np->errors) == EOF)
  228.                 break;
  229.  
  230.     return 0;
  231. }
  232.  
  233. #endif /* NRS */
  234. #endif /* NETROM */
  235.